﻿using MicroDb.Mysql;
using MicroDb.Querys;

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

using MySqlConnector;

using System;
using System.Collections.Concurrent;
using System.Data.Common;
using System.Linq;
using System.Reflection;

namespace MicroDb
{
    class DBQueryProviderFactory
    {
        private static ConcurrentDictionary<string, SqlExecute> ConnectionStrings = new ConcurrentDictionary<string, SqlExecute>();
        public static IQueryProvider CreateQueryProvider(IServiceProvider serviceProvider, Type dbModelType)
        {
            var attr = dbModelType?.GetCustomAttribute<DbSourceAttribute>();
            string dbSource = attr?.Name ?? "Default";
            return ActivatorUtilities.CreateInstance<DBQueryProvider>(serviceProvider, dbSource);
        }

        public static bool Remove(string dbSource)
        {
            return ConnectionStrings.TryRemove(dbSource, out _);
        }

        private static SqlExecute CreateSqlExecute(IServiceProvider serviceProvider, string connectionString, MicroDbType microDbType)
        {
            switch (microDbType)
            {
                case MicroDbType.MySql:
                    var dbConnectionStringBuilder = new MySqlConnectionStringBuilder(connectionString)
                    {
                        Pooling = true,
                        MaximumPoolSize = 50,
                        MinimumPoolSize = 3,
                        ConnectionIdleTimeout = 60,
                        ConnectionLifeTime = 60 * 60
                    };
                    return ActivatorUtilities.CreateInstance<MySqlExecute>(serviceProvider, dbConnectionStringBuilder.ConnectionString);
                case MicroDbType.SqlServer:
                    break;
                case MicroDbType.Oracle:
                    break;
                default:
                    break;
            }
            return null;
        }

        /// <summary>
        /// 获取sql执行器
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="dbSource"></param>
        /// <param name="microDbType"></param>
        /// <returns></returns>
        public static SqlExecute GetSqlExecute(IServiceProvider serviceProvider, string dbSource, string connectionString, MicroDbType microDbType)
        {
            return ConnectionStrings.GetOrAdd(dbSource, key => CreateSqlExecute(serviceProvider, connectionString, microDbType));
        }
    }
}
